local function flameColor(game)
    return math.floor(240 * (1.5 + game.rng:random())),
        math.floor(120 * (1 + game.rng:random())),
        math.floor(60 * (0 + game.rng:random()))
end

return {
    ['heal'] = {
        name = 'heal',
        info = 'Instantly recovers half maximum health.',
        evoke = function(mob, game)
            mob.health = math.min(mob.maxHealth, mob.health + mob.maxHealth * 0.5)
            if mob == game.player then
                game:log('You feel healthier.')
            elseif mob.visible then
                game:log(mob.definite, ' looks healthier.')
            end
            return true
        end,
    },
    ['regen'] = {
        name = 'regen',
        info = 'Boosts health regeneration for a while.',
        duration = 100,
        evoke = function(mob, game)
            mob.healthRegen = mob.healthRegen + 0.2
            if mob == game.player then
                game:log('You begin to regenerate.')
            elseif mob.visible then
                game:log(mob.definite, ' begins to regenerate.')
            end
            return true
        end,
        revoke = function(mob, game)
            mob.healthRegen = mob.healthRegen - 0.2
            if mob == game.player then
                game:log('Your regeneration ends.')
            elseif mob.visible then
                game:log(mob.definite, ' stops regenerating.')
            end
            return true
        end,
    },

    ['confuse'] = {
        name = 'confuse',
        info = 'Causes victims to stumble around.',
        stack = 1,
        duration = 100,
        evoke = function(mob, game)
            if mob == game.player then game:log('You are confused.')
            elseif mob.visible then game:log(mob.definite, ' looks confused.')
            end
            return true
        end,
        revoke = function(mob, game)
            if mob == game.player then game:log('You come to your senses.')
            elseif mob.visible then game:log(mob.definite, ' looks less confused.')
            end
            return true
        end,
        active = function(mob, game, count)
            local scene = game.scene
            if mob.command == 'read' then
                if mob == game.player then
                    game:log("You're too confused to read anything.")
                end
                return true
            end
            if mob.command == 'wait' then
                return false -- player resting overcomes effect
            end
            if game:roll(2, 10) < mob.int then
                return false -- roll 2d10 < mob.int overcomes effect
            end
            local vx, vy = game:roll(1, 3) - 2, game:roll(1, 3) - 2
            local newX, newY = mob.x + vx, mob.y + vy
            if vx == 0 and vy == 0 then
                if mob == game.player then game:log('You falter.')
                elseif mob.visible then game:log(mob.definite, ' falters.')
                end
            elseif scene:canMove(mob, newX, newY) then
                if mob == game.player then
                    scene:movePlayer(vx, vy)
                    game:log('You stumble around.')
                else
                    scene:move(mob, newX, newY)
                    if mob.visible then game:log(mob.definite, ' stumbles around.') end
                end
            elseif scene:canAttack(mob, newX, newY) then
                target = scene:getMob(newX, newY)
                if not target then return true end
                scene:attack(mob, target)
                if mob == game.player then game:log('You stumble into ', target.indefinite, '.')
                elseif mob.visible then game:log(mob.definite, ' stumbles into ', target.indefinite, '.')
                end
            else
                local f = scene:getFeature(newX, newY)
                if mob == game.player then game:log('You bump into the ', f.name, '.')
                elseif mob.visible then game:log(mob.definite, ' bumps into the ', f.name, '.')
                end
            end
            return true
        end,
    },
    ['venom'] = {
        name = 'venom',
        info = 'Causes health to degenerate for a while.',
        duration = 500,
        stack = 3,
        chance = 1/3,
        evoke = function(mob, game, count)
            mob.healthRegen = mob.healthRegen - 0.1
            local sick = count == 1 and 'sick.'
                or count == 2 and 'sicker.'
                or count == 3 and 'as sick as possible.'
            if mob == game.player then
                game:log('You feel ', sick)
            elseif mob.visible then
                game:log(mob.definite, ' looks ', sick)
            end
            return true
        end,
        revoke = function(mob, game, count)
            mob.healthRegen = mob.healthRegen + 0.1
            if count then return end -- bumped by a renewal
            if mob == game.player then
                game:log('The effects of the venom subside.')
            elseif mob.visible then
                game:log(mob.definite, ' recovers from the venom.')
            end
            return true
        end,
    },

    ['inner flame'] = {
        name = 'inner flame',
        info = 'Victims explode upon death.',
        duration = 200,
        stack = 1,
        chance = 1,
        evoke = function(mob, game, count)
            if mob == game.player then
                game:log('You are filled with an inner flame.')
            elseif mob.visible then
                game:log(mob.definite, ' is filled with an inner flame.')
            end
            mob.realColor = mob.color
            mob.color = { flameColor(game) }
            return true
        end,
        revoke = function(mob, game, count)
            if mob == game.player then
                game:log('You are no longer filled with an inner flame.')
            elseif mob.visible then
                game:log(mob.definite, ' is no longer filled with an inner flame.')
            end
            mob.color = mob.realColor
            return true
        end,
        passive = function(mob, game, count)
            mob.color[1], mob.color[2], mob.color[3] = flameColor(game)

            if game.turns % 5 == 0 then  -- smoke every 5 ticks
                game.scene:putCloud(mob.x, mob.y, 'smoke', { duration = 50 })
            end

            if mob.health > 1 then return end
            if mob == game.player then
                game:log('You explode!')
            elseif mob.visible then
                game:log(mob.definite, ' explodes!')
            end
            for x = mob.x - 1, mob.x + 1 do for y = mob.y - 1, mob.y + 1 do
                game.scene:putCloud(x, y, 'flame', { duration = 100 + game:roll(2, 50) })
            end end
            return true
        end,
    },
    ['entangle'] = {
        name = 'entangle',
        info = 'Holds victims in place, greatly reducing dexterity.',
        duration = 50,
        stack = 1,
        chance = 1,
        evoke = function(mob, game, count)
            mob.delay = mob.delay + 50
            mob.dex = mob.dex - 8
            if mob == game.player then
                game:log('You are entangled.')
            elseif mob.visible then
                game:log(mob.definite, ' becomes entangled,')
            end
            return true
        end,
        revoke = function(mob, game, count)
            if count then return end -- bumped by a renewal
            mob.dex = mob.dex + 8
            if mob == game.player then
                game:log('You are no longer entangled.')
            elseif mob.visible then
                game:log(mob.definite, ' is no longer entangled.')
            end
            return true
        end,
        passive = function(mob, game, count)
            if game.turns % 5 ~= 0 then return end -- every 5 ticks
            if mob == game.player then
                game:log('You struggle against the vines.')
            elseif mob.visible then
                game:log(mob.definite, ' struggles against the vines.')
            end
            return true
        end,
    },
    ['fog'] = {
        name = 'fog',
        info = 'Forms a thick fog, obscuring vision.',
        duration = 1000,
        stack = 1,
        chance = 1,
        evoke = function(mob, game, count)
            if mob == game.player or mob.visible then
                game:log('A thick fog begins to form around ', mob.definite)
            end
            return true
        end,
        revoke = function(mob, game, count)
            return true
        end,
        passive = function(mob, game, count)
            if game.turns % 5 ~= 0 then return end -- every 5 ticks
            for x = mob.x - 1, mob.x + 1 do for y = mob.y - 1, mob.y + 1 do
                game.scene:putCloud(x, y, 'fog', { duration = 2000 })
            end end
            return true
        end,
    },

    ['burn'] = {
        name = 'burn',
        info = 'Burns its victims.',
        chance = 1,
        duration = 20,
        stack = 20,
        evoke = function(mob, game, count)
            if mob == game.player then
                game:log('You are burned.')
            elseif mob.visible then
                game:log(mob.definite, ' is burned.')
            end
            -- mob.color, mob.realColor = mob.realColor or { flameColor(game) }, mob.color
            return true
        end,
        revoke = function(mob, game, count)
            -- mob.color, mob.realColor = mob.realColor, mob.color
            return true
        end,

        passive = function(mob, game, count)
            mob.health = mob.health - 1
            game.scene:putCloud(mob.x, mob.y, 'smoke')
            return true
        end,
    },

    ['ninja'] = {
        name = 'ninja',
        info = 'u ninja.',
        stack = 1,
        duration = 1000,
        evoke = function(mob, game)
            mob.dex = mob.dex + 5
            mob.speed = mob.speed + 2
            mob.sneaking = mob.sneaking + 2
            if mob == game.player then game:log('You feel like a ninja.')
            elseif mob.visible then game:log(mob.definite, ' looks like a ninja.')
            end
            return true
        end,
        revoke = function(mob, game)
            mob.dex = mob.dex - 5
            mob.speed = mob.speed - 2
            mob.sneaking = mob.sneaking - 2
            if mob == game.player then game:log('You feel less ninja-like.')
            elseif mob.visible then game:log(mob.definite, ' looks less ninja-like.')
            end
            return true
        end,
        active = function(mob, game, count)

            local vx, vy

            if mob.command == 'move_n' then vx, vy = 0, -1
            elseif mob.command == 'move_ne' then vx, vy = 1, -1
            elseif mob.command == 'move_e' then vx, vy = 1, 0
            elseif mob.command == 'move_se' then vx, vy = 1, 1
            elseif mob.command == 'move_s' then vx, vy = 0, 1
            elseif mob.command == 'move_sw' then vx, vy = -1, 1
            elseif mob.command == 'move_w' then vx, vy = -1, 0
            elseif mob.command == 'move_nw' then vx, vy = -1, -1
            end

            if not vx then return false end

            local scene = game.scene

            local newX, newY = mob.x + vx, mob.y + vy

            -- lunge
            if scene:canMove(mob, newX, newY) then
                local target = scene:getMob(newX + vx, newY + vy)
                if target then
                    if mob == game.player then game:log('You lunge at ', target.definite, '!')
                    elseif mob.visible then game:log(mob.definite, ' lunges at ', target.definite, '!')
                    end
                    mob.delay = 0
                    while mob.delay < 20 do
                        scene:attack(mob, target)
                    end
                    mob.delay = 0
                end
            -- walljump
            else
                local landX, landY = mob.x - vx - vx, mob.y - vy - vy
                local f1 = scene:getFeature(newX, newY)
                local f2 = scene:getFeature(landX, landY)
                if f1.obstruct and not f1.opened and scene:canMove(mob, landX, landY) then

                    if mob == game.player then
                        game:log('You backflip off the ', f1.name, '.')
                        scene:movePlayer(-vx - vx,  -vy - vy)
                    else
                        if mob.visible then game:log(mob.definite, ' backflips off the ', f1.name, '.') end
                        scene:move(mob, landX, landY)
                    end
                    return true
                end
            end


        end,
    },

}